# -*- coding: utf-8 -*-
from flask import (
    Blueprint,
    make_response,
    render_template,
    current_app,
    request,
    jsonify
)
from werkzeug.local import LocalProxy
import rpyc


from .. import template_folder, static_folder
from ..utils import netref2builtins

task_rpyc = LocalProxy(lambda: current_app.task_rpyc)
task_list = LocalProxy(lambda: current_app.task_list)
task_flow = LocalProxy(lambda: current_app.task_flow)
socketio = LocalProxy(lambda: current_app.socketio)

NAME = 'passage'
passage_app = Blueprint(
    NAME,
    __name__,
    template_folder=template_folder,
    static_folder=static_folder
)

def get_task_list():
    '''获取任务列表'''
    global task_rpyc
    global task_list
    # 如何和rpyc服务端断开了，则自动重新连接
    if isinstance(task_list, rpyc.core.BaseNetref):
        _conn = getattr(task_list, "____conn__")()
        if not bool(_conn):
            task_list = task_rpyc.get_task_list()
        else:
            try:
                task_list = task_list.copy()
            except EOFError as e:
                task_list = task_rpyc.get_task_list()
    else:
        if not bool(task_list):
            task_list = task_rpyc.get_task_list()
    return task_list

def get_task_flow():
    '''获取任务流程'''
    global task_rpyc
    global task_flow
    # 如何和rpyc服务端断开了，则自动重新连接
    if isinstance(task_flow, rpyc.core.BaseNetref):
        _conn = getattr(task_flow, "____conn__")()
        if not bool(_conn):
            task_flow = task_rpyc.get_task_flow()
        else:
            try:
                task_flow = task_flow.copy()
            except EOFError as e:
                task_flow = task_rpyc.get_task_flow()
    else:
        if not bool(task_flow):
            task_flow = task_rpyc.get_task_flow()
    return task_flow

@passage_app.route('/tab/task-start')
def tab_passage_task_start():
    task_dict = netref2builtins(get_task_list())
    task_list = []
    for _id in task_dict:
        _item = task_dict[_id].copy()
        _item['id'] = _id
        task_list.append(_item)
    # debug:
    # import json
    # print(json.dumps(task_list, ensure_ascii=False, indent=4))
    resp = make_response(render_template('ajax/passage/task-start.html', task_list=task_list))
    resp.headers['Content-type'] = 'text/plain; charset=utf-8'
    return resp

@passage_app.route('/tab/task-start-flow')
def tab_passage_task_start_flow():
    task_dict = netref2builtins(get_task_flow())
    task_list = []
    for _id in task_dict:
        _item = task_dict[_id].copy()
        _item['id'] = _id
        task_list.append(_item)
    # debug:
    # import json
    # print(json.dumps(task_list, ensure_ascii=False, indent=4))
    resp = make_response(render_template('ajax/passage/task-start-flow.html', task_list=task_list))
    resp.headers['Content-type'] = 'text/plain; charset=utf-8'
    return resp

@passage_app.route('/tab/task-view')
def tab_passage_task_view():
    resp = make_response(render_template('ajax/passage/task-view.html'))
    resp.headers['Content-type'] = 'text/plain; charset=utf-8'
    return resp

@passage_app.route('/tab/result-log')
def tab_passage_result_log():
    resp = make_response(render_template('ajax/passage/result-log.html'))
    resp.headers['Content-type'] = 'text/plain; charset=utf-8'
    return resp

@passage_app.route('/ajax/task', methods=['GET', 'POST'])
def ajax_task():
    task_dict = netref2builtins(get_task_list())
    (error, task, mode, value_params, type_params) = verify_task_params(task_dict, request.values)
    if error is not None:
        return jsonify({
            'error': 1,
            'msg': error
        })
    task_params = {
        'task': task,
        'mode': mode,
        'params': value_params,
        'mode_params': type_params
    }
    rpyc_r = task_rpyc.send_task(task_params)
    if rpyc_r is None:
        return jsonify({
            'error': 2,
            'msg': '添加任务失败, 服务器错误'
        })
    result = {}
    for k in rpyc_r:
        result[k] = rpyc_r[k]
    ret = {
        'error': 0,
        'msg': '添加任务成功',
        'data': {
            'job_id': result
        }
    }
    return jsonify(ret)

@passage_app.route('/ajax/task-flow', methods=['GET', 'POST'])
def ajax_task_flow():
    task_dict = netref2builtins(get_task_flow())
    (error, task_flow, _params) = verify_task_flow_params(task_dict, request.values)
    if error is not None:
        return jsonify({
            'error': 1,
            'msg': error
        })
    task_params = {
        'task': task_flow,
        'params': _params
    }
    rpyc_r = task_rpyc.send_task_flow(task_params)
    if rpyc_r is None:
        return jsonify({
            'error': 2,
            'msg': '添加任务失败, 服务器错误'
        })
    result = {}
    for k in rpyc_r:
        result[k] = rpyc_r[k]
    ret = {
        'error': 0,
        'msg': '添加任务成功',
        'data': {
            'job_id': result
        }
    }
    return jsonify(ret)


def get_keys(val, prefix):
    keys = {}
    for item in val[prefix]:
        key = prefix + '[' + item['name'] + ']'
        keys[key] = item
    return keys

def verify_task_params(task_dict, c_params):
    error = None
    value_params = []
    type_params = []
    task = c_params.get('task', None) # task id
    mode = c_params.get('mode', None) # task 类型
    if bool(task) and task in task_dict:
        t_define = task_dict[task]
        t_modes = t_define['modes']
        if bool(mode) and mode in t_modes:
            t_mode = t_modes[mode]
            v_keys = get_keys(t_mode, 'params') # 任务参数
            m_keys = get_keys(t_mode, 'type_params') # 类型参数
            for vk in v_keys:
                vv = v_keys[vk]
                cv = c_params.get(vk, None)
                if vv['required'] and not bool(cv):
                    print(mk)
                    error = '缺少参数[{0}]'.format(vv['text'])
                    break
                value_params.append({
                    vv['name']: cv
                })
            for mk in m_keys:
                mv = m_keys[mk]
                cv = c_params.get(mk, None)
                if mv['required'] and not bool(cv):
                    print(mk)
                    error = '缺少参数[{0}]'.format(mv['text'])
                    break
                type_params.append({
                    mv['name']: cv
                })
        else:
            error = 'mode is required'
    else:
        error = 'task is required'
    return (error, task, mode, value_params, type_params)

def verify_task_flow_params(task_dict, c_params):
    error = None
    _params = []
    task = c_params.get('task', None)
    if bool(task) and task in task_dict:
        t_define = task_dict[task]
        v_keys = get_keys(t_define, 'params')
        for vk in v_keys:
            vv = v_keys[vk]
            cv = c_params.get(vk, None)
            if vv['required'] and not bool(cv):
                print(mk)
                error = '缺少参数[{0}]'.format(vv['text'])
                break
            _params.append({
                vv['name']: cv
            })
    else:
        error = 'task is required'
    return (error, task, _params)